package com.wangku.springmvc.aspect;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.google.gson.Gson;

/**
 * @author Administrator
 * 日志切面类
 */
@Aspect
@Component
public class ApiLogAspect {
	private static final Logger LOGGER = LoggerFactory.getLogger(ApiLogAspect.class);

	private static final Gson GSON = new Gson();

	@Pointcut("execution(* com.wangku.springmvc.controller.*.*(..))")
	public void controllerAspect() {
	}

	@Around("controllerAspect()")
	public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
		long startTime = System.currentTimeMillis();
		Object responseObj = joinPoint.proceed();
		handleLog(startTime, responseObj, joinPoint);
		return responseObj;
	}

	private void handleLog(long startTime, Object responseObj, ProceedingJoinPoint joinPoint) {
		Map<String, Object> logMap = new LinkedHashMap<>();
		logMap.put("duration", (System.currentTimeMillis() - startTime) + "ms");
		
		HttpServletRequest request = getRequest();
		Map<String, Object> requestMap = new HashMap<>();
		requestMap.put("ipAddress", getIpAddress(request));
		requestMap.put("url", request.getRequestURL().toString());
		requestMap.put("params", request.getParameterMap());
		requestMap.put("method", request.getMethod());
		logMap.put("request", requestMap);
		
		logMap.put("response", responseObj);
		LOGGER.info(getMethodName(joinPoint) + ":"+ GSON.toJson(logMap));
		
	}

	private String getMethodName(ProceedingJoinPoint joinPoint) {
		return joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName();
	}

	private HttpServletRequest getRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	private String getIpAddress(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
	
}
